package tum0r.json;

import tum0r.utils.GetFields;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.*;

/**
 * 工程: XJSON<br>
 * 包: tum0r.json<br>
 * 创建者: tum0r<br>
 * 创建时间: 2020/9/20 13:13<br>
 * <br>
 */
public class JSONReader {
    public static <T> T deserialize(String data, Class<?> c) {
        return deserialize(JSONObject.parse(data), c);
    }

    public static <T> T deserialize(JSON data, Class<?> c) {
        T result = null;
        try {
            if (data != null && c != null) {
                GetFields getFields = new GetFields();
                LinkedList<Field> fields = getFields.getFields(c);
                result = (T) c.getConstructor().newInstance();
                for (Field field : fields) {
                    String key = field.getName();
                    if (data.containsKey(key)) {
                        Class<?> fieldType = field.getType();
                        String fieldTypeName = fieldType.getCanonicalName();
                        if (fieldTypeName.equals(Byte.class.getCanonicalName()) ||
                                fieldTypeName.equals(byte.class.getCanonicalName()) ||
                                fieldTypeName.equals(Short.class.getCanonicalName()) ||
                                fieldTypeName.equals(short.class.getCanonicalName()) ||
                                fieldTypeName.equals(Integer.class.getCanonicalName()) ||
                                fieldTypeName.equals(int.class.getCanonicalName()) ||
                                fieldTypeName.equals(Long.class.getCanonicalName()) ||
                                fieldTypeName.equals(long.class.getCanonicalName()) ||
                                fieldTypeName.equals(Double.class.getCanonicalName()) ||
                                fieldTypeName.equals(double.class.getCanonicalName()) ||
                                fieldTypeName.equals(Float.class.getCanonicalName()) ||
                                fieldTypeName.equals(float.class.getCanonicalName()) ||
                                fieldTypeName.equals(Character.class.getCanonicalName()) ||
                                fieldTypeName.equals(char.class.getCanonicalName()) ||
                                fieldTypeName.equals(Boolean.class.getCanonicalName()) ||
                                fieldTypeName.equals(boolean.class.getCanonicalName()) ||
                                fieldTypeName.equals(String.class.getCanonicalName())
                        ) {
                            field.set(result, data.getJsonNode(key).getObject());
                        } else {
                            boolean flag = fieldType.isArray();
                            if (!flag) {
                                try {
                                    fieldType.asSubclass(Collection.class);
                                    flag = true;
                                } catch (Exception ignored) {
                                }
                            }

                            if (!flag) {
                                try {
                                    fieldType.asSubclass(Map.class);
                                    flag = true;
                                } catch (Exception ignored) {
                                }
                            }

                            if (!flag) {
                                try {
                                    fieldType.asSubclass(Enumeration.class);
                                    flag = true;
                                } catch (Exception ignored) {
                                }
                            }

                            if (!flag) {
                                try {
                                    fieldType.asSubclass(Dictionary.class);
                                    flag = true;
                                } catch (Exception ignored) {
                                }
                            }

                            if (!flag) {
                                field.set(result, JSONReader.deserialize(data.getJsonNode(key).getJSON(), field.getType()));
                            }
                        }
                    }
                }
            }
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            e.printStackTrace();
        }
        return result;
    }
}
